STAT4 : RELATION ENTRE DEUX VARIABLES QUALITATIVES

Exo1 : Tableau de contingence et test du chi-2

Auteur·rice

Jean-Paul NGBESSO & Claude GRASLAND

Date de publication

2025-05-27

Le but de ce TD est de mettre en oeuvre le cours sur le tableau de contingence et le test du chi-2 fournissant un programme type d’analyse de la relation entre deux variables X et Y qualitatives à l’aide de R. Ce programme pourra ensuite être facilement adapaté à d’autres jeux de données.

Télécharger l’exercice

1. PREPARATION DES DONNEES

1.1. Chargement des données

On charge un fichier contenant les résultats d’une enquête.

  • Très important : On ajoute l’instruction stringAsFactors=TRUE pour que toutes les variables de type caractère deveiennent des variables de type factor.
don <- read.table(file = "data/civ_afrobarometer_2023/data/survey_data.csv", # nom du fichier et chemin d'accès
                  sep = ";",                     # séparateur (ici, des points-virgule)
                  dec=",",                       # Type de décimale
                  header = TRUE,                 # ligne d'en-tête avec le nom des variables
                  encoding="UTF-8",              # encodage adapté au français
                  stringsAsFactors = TRUE)       # Transforme les character en factor     

1.2 Chargement des métadonnées

On charge ensuite un tableau contenant des informations sur les variables et leurs modalités

meta <- read.table(file = "data/civ_afrobarometer_2023/data/survey_meta.csv", # nom du fichier et chemin d'accès
                  sep = ";",                     # séparateur (ici, des points-virgule)
                  dec=",",                       # Type de décimale
                  header = TRUE,                 # ligne d'en-tête avec le nom des variables
                  encoding="UTF-8")              # encodage adapté au français

## Affichage des métadonnées
meta
          code
1       RESPNO
2  withinwt_ea
3       URBRUR
4       REGION
5     EA_SVC_A
6     EA_SVC_B
7     EA_FAC_B
8    EA_ROAD_C
9      THISINT
10    ADULT_CT
11       CALLS
12          Q1
13          Q2
14        Q46F
15        Q46G
16        Q46H
17        Q46I
18        Q57A
19        Q57B
20        Q58A
21        Q58C
22        Q90D
23        Q90F
24        Q90G
25        Q91C
26        Q92A
27         Q94
28      LENGTH
29        Q101
30        Q102
31        Q103
                                                                     def
1                                                    Numéro du répondant
2                                       Facteur de pondération nationale
3                                        Type de milieu: Urbain ou Rural
4                                                                 Région
5                                 EA-SVC-A. Réseau électrique dans la ZD
6                         EA-SVC-B. Système d'adduction d'eau dans la ZD
7                                             EA-FAC-B. École dans la ZD
8                       EA-ROAD-C. État de la route sur les derniers 5km
9                                                    Cet entretien, sexe
10                             Nombre de citoyens adultes dans le ménage
11                                                     Nombre de visites
12                                                               Q1. Age
13                                      Q2. Langue parlée dans le ménage
14                                     Q46f. Réduction de la criminalité
15                      Q46g. Amélioration des services de santé de base
16                           Q46h. Satisfaction des besoins en éducation
17                Q46i. Fourniture de services d'eau et d'assainissement
18                                 Q57a. Est tombé malade de la COVID-19
19                          Q57b. Perte de revenu à cause de la COVID-19
20                             Q58a. A reçu le vaccin contre la COVID-19
21 Q58c. Raison principale pour laquelle il est peu probable de vacciner
22                                              Q90d. Possède ordinateur
23                                      Q90f. Possède téléphone portable
24                               Q90g. Téléphone a un accès à l’Internet
25                           Q91c. Emplacement de la toilette ou latrine
26                           Q92a. Maison raccordée au réseau électrique
27                                Q94. Niveau d'instruction du répondant
28                                                  Durée de l'entretien
29                                              Q101.  Sexe du répondant
30                                              Q102.  Race du répondant
31                                Q103. Langue principale de l'entretien

1.3 Choix de variables à analyser

On sélectionne dans le tableau une variable Y que l’on veut expliquer et des variables X1, X2 …X3 qui peuvent servir à expliquer Y. On décide par exemple d’examiner les variables suivantes :

  • vac : A été vacciné contre le covid (Q58A)
  • sex : Sexe (Q101)
  • age : Age (Q1)
  • mil : Milieu Urbain ou rural (URBRUR)
  • ins : Niveau d’instruction (Q94)
sel<-don[,c("Q58A","Q101","Q1","URBRUR","Q94")]
colnames(sel)<-c("vac","sex","age","mil","ins")
head(sel)
  vac   sex age    mil                                      ins
1 Non Femme  27 Urbain                     Université inachevée
2 Non Femme  52 Urbain                       Université achevée
3 Oui Homme  21 Urbain Enseignement secondaire / lycée inachevé
4 Oui Femme  45  Rural           Enseignement primaire inachevé
5 Oui Homme  76  Rural                Pas d’enseignement formel
6 Oui Homme  66 Urbain Enseignement secondaire / lycée inachevé

1.3 Recodage de variables qualitative

On veut simplifier la variable reltive au niveau d’instruction qui possède trop de classes. On commence par examiner la distribution des fréquences

table(sel$ins)

                                                                                              A refusé 
                                                                                                     1 
                                  Enseignement informel seulement  (y compris enseignement coranique ) 
                                                                                                    36 
                                                                          Enseignement primaire achevé 
                                                                                                    85 
                                                                        Enseignement primaire inachevé 
                                                                                                   235 
                                                                Enseignement secondaire / lycée achevé 
                                                                                                    94 
                                                              Enseignement secondaire / lycée inachevé 
                                                                                                   402 
                                                                                           Ne sait pas 
                                                                                                     5 
                                                                             Pas d’enseignement formel 
                                                                                                   165 
                                                                                    Post universitaire 
                                                                                                     2 
Qualifications post-secondaires autres qu’universitaires (certificat ou diplôme d'école polytechnique) 
                                                                                                    32 
                                                                                    Université achevée 
                                                                                                    65 
                                                                                  Université inachevée 
                                                                                                    78 

Puis on recode chaque niveau avec l’instruction levels(). On indique NA pour les non réponses.

sel$ins4<-sel$ins
levels(sel$ins4) <- c(NA,
                     "Inf.",
                     "Prim.",
                     "Prim.",
                     "Sec.",
                     "Sec.",
                     NA,
                     "Inf.",
                     "Sup.",
                     "Sup.",
                     "Sup.",
                     "Sup."
                     )
table(sel$ins4)

 Inf. Prim.  Sec.  Sup. 
  201   320   496   177 

1.4 Découpage de variables quantitatives

On veut découper la variable âge en trois classes :

summary(sel$age)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  18.00   24.00   32.00   34.84   42.00   85.00 
sel$age3 <-cut(sel$age, breaks=c(17, 29, 50,100))
levels(sel$age3) <-c("- de 30 ans","30-50 ans", "+ de 50 ans")
table(sel$age3)

- de 30 ans   30-50 ans + de 50 ans 
        482         559         159 

1.5 Elimination des valeurs manquantes

On ne garde que les lignes du tableau qui sont complètes car autrement il risque d’y avoir des problèmes dans les analyses.

sel <-sel[complete.cases(sel), ]

1.6 Resumé du tableau

Proposez un résumé rapide du tableau

summary(sel)
  vac         sex           age            mil     
 Non:764   Femme:598   Min.   :18.00   Rural :542  
 Oui:430   Homme:596   1st Qu.:25.00   Urbain:652  
                       Median :32.00               
                       Mean   :34.85               
                       3rd Qu.:42.00               
                       Max.   :85.00               
                                                   
                                       ins         ins4              age3    
 Enseignement secondaire / lycée inachevé:402   Inf. :201   - de 30 ans:479  
 Enseignement primaire inachevé          :235   Prim.:320   30-50 ans  :557  
 Pas d’enseignement formel               :165   Sec. :496   + de 50 ans:158  
 Enseignement secondaire / lycée achevé  : 94   Sup. :177                    
 Enseignement primaire achevé            : 85                                
 Université inachevée                    : 78                                
 (Other)                                 :135                                

2. ANALYSE UNIVARIEE

Quelles sont les étapes d’analyse d’une variable qualitative de type factor ? On va proposer ci-dessous un programme type

2.1 : Analyse de la variable à expliquer (dépendante) Y

On suppose que la variable à expliquer est le fait d’être vacciné

Fréquence simple

En l’absence de pondération il suffit de calculer les fréquences avec l’instruction table()puis de les afficher en ajoutant le total avec addmargins()

mytab1 <-table(sel$vac)
mytab1

Non Oui 
764 430 
  • Commentaire : 768 personnes déclarent avoir été vaccinées contre 432 qui déclarent ne pas l’avoir été

Pourcentage

On veut ensuite facilement calculer les valeurs en pourcentage en utlisant la fonction prop.table() de R-base

100*prop.table(mytab1)

    Non     Oui 
63.9866 36.0134 
  • Commentaire : Les personnes vaccinées représentent 64% des réponses, les non vaccinés 36%

Diagramme en bâton

on veut visualiser la table avec barplot() :

barplot(mytab1)

Améliorer le graphique avec des titres et des couleurs

barplot(mytab1, 
        main = "Y : Vaccination contre le Covid en Côte d'Ivoire",
        sub = "Source : Afrobarometer 2023",
        col = c("red","blue"))

Camembert

On peut également faire un camenbert si on préfère avec pie()

pie(mytab1, 
        main = "Vaccination contre le Covid en Côte d'Ivoire",
        sub = "Source : Afrobarometer 2023",
        col = c("red","blue"))

2.2 Analyse de la variable explicative (indépendante) X

On suppose que la variable explicative (indépendante) est age3 (âge en trois classes)

Fréquence simple

Calculer les fréquences de chaque classe

mytab2 <-table(sel$age3)
mytab2

- de 30 ans   30-50 ans + de 50 ans 
        479         557         158 
  • Commentaire : On trouve 479 personnes de - de 30 ans, 459 de 30-44 ans, 180 de 45-59 ans, 76 de 60 ans et +.

Pourcentage

On peut ensuite facilement calculer les valeurs en pourcentage en utlisant la fonction prop.table() de R-base

100*prop.table(mytab2)

- de 30 ans   30-50 ans + de 50 ans 
   40.11725    46.64992    13.23283 
  • Commentaire : Notre échantillon comporte 40% de jeunes, 45% d’adultes et 15% de vieux.

Diagramme en bâton

Visualiser la table avec barplot :

barplot(mytab2)

Améliorer le graphique en ajoutant des titres et des couleurs adaptées :

barplot(mytab2, 
        main = " X : Âge des personnes enquêtées ",
        sub = "Source : Afrobarometer 2023",
        col = c("yellow","orange","brown"))

3. ANALYSE BIVARIEE

Objectif

On veut tester l’existence d’une relation entre les deux variables précédentes. Vous devez formuler deux hypothèses alternatives :

H0 : Il n’y a pas de relation entre X et Y H1 : Il y a une relation entre X et Y

3.1 Création du tableau de contingence

Tableau brut

Créer un tableau de contingence en indiquant en premier la variable indépendante (X) et en second la variable à expliquer (Y)

tabcont<-table(sel$age3,sel$vac)
tabcont
             
              Non Oui
  - de 30 ans 336 143
  30-50 ans   346 211
  + de 50 ans  82  76

Ajout des marges

Ajouter à votre tableau les sommes des lignes et des colonnes :

tabtot <- addmargins(tabcont)
tabtot
             
               Non  Oui  Sum
  - de 30 ans  336  143  479
  30-50 ans    346  211  557
  + de 50 ans   82   76  158
  Sum          764  430 1194

Pourcentage en ligne

Calculez les pourcentages en lignes pour voir si la fréquence des modalités de Y varie en fonction de celles de X

tabpct <- 100*prop.table(tabcont,1) # Calcule le pourcentage en ligne (1)
round(tabpct,1)                     # Arrondi à un chiffre après la virgule
             
               Non  Oui
  - de 30 ans 70.1 29.9
  30-50 ans   62.1 37.9
  + de 50 ans 51.9 48.1
  • Commentaire : Il semble en effet y avoir une relation entre les deux variables. Le taux de personnes vaccinés est plus faible chez les jeunes (30%) que chez les adultes (38%) ou les vieux (48%).

3.2 Visualisation de la relation

Construire un graphique en mosaïque avec mosaicplot()

mosaicplot(tabcont)

Améliorer le graphique avec des titres et des couleurs :

mosaicplot(tabcont, 
           main= "Vaccination et âge en Côte d'Ivoire en 2021",
           sub = "Source : Afrobarometer",
           xlab = "Classes d'âge",
           ylab = "Vaccination Covid",
           col = c("red","blue"))

3.3 Test du chi-2

On va tester si les différences de pourcentage sont significatives ou sont l’effet du hasard.

Hypothèse nulle

Rappelez l’hypothèse H0 :

H0 : il n’y a pas de relation entre X et Y. Les variations en Y en fonction de X sont l’effet du hasard.

Test

Réalisez un test du chi-2 à l’aide de la fonction chisq.test() et commentez les résultats du test.

chisq.test(tabcont)

    Pearson's Chi-squared test

data:  tabcont
X-squared = 18.748, df = 2, p-value = 8.488e-05
  • Commentaire : Notre tableau comportait 3 lignes et 2 colonnes et avait donc 2 degrés de liberté. Le chi-2 du tableau est de 18.74 ce qui donne une p-value de 0.000085. Il y a donc moins d’une chance sur 1000 (p < 0.001) que les différences soient l’effet du hasard et que H0 soit vraie.

Conclusion

Au vu des résultats on rejette H0 et on accepte H1. On conclue avec un risque d’erreur très faible (p < 0.001) qu’il existe une relation entre l’âge et le fait d’être vacciné en Côte d’Ivoire en 2021.

L’explication paraît à première vue assez simple. En effet la pandémie de Covid était particulèrement dangereuse pour les personnes âgées, ce qui a pu pousser à les vacciner en priorité. Mais d’autres interprétations ne sont pas à exclure. Par exemple une plus grande méfiance des jeunes ? une plus grande insouciance ? des revenus insuffisants pour payer le vaccin ? etc.

4. A VOUS DE JOUER…

Testez rapidement trois autres relations possibles

4.1 Vaccination et sexe

# tableau de contingence
tabcont <- table(sel$sex,sel$vac)
tabcont
       
        Non Oui
  Femme 403 195
  Homme 361 235
# Pourcentages
prop.table(tabcont,1)
       
              Non       Oui
  Femme 0.6739130 0.3260870
  Homme 0.6057047 0.3942953
# graphique
plot(tabcont)

# test
chisq.test(tabcont)

    Pearson's Chi-squared test with Yates' continuity correction

data:  tabcont
X-squared = 5.7341, df = 1, p-value = 0.01664
  • Conclusion : Les femmes sont dans l’ensemble moins vaccinées (32.5%) que les hommes (39.5%). On peut affirmer avec un risque d’erreur inférieur à 0.05 que cette relation est significative.

4.2 Vaccination et milieu urbain-rural

# tableau de contingence
tabcont <- table(sel$mil,sel$vac)
tabcont
        
         Non Oui
  Rural  332 210
  Urbain 432 220
# Pourcentages
prop.table(tabcont,1)
        
               Non       Oui
  Rural  0.6125461 0.3874539
  Urbain 0.6625767 0.3374233
# graphique
plot(tabcont)

# test
chisq.test(tabcont)

    Pearson's Chi-squared test with Yates' continuity correction

data:  tabcont
X-squared = 3.0014, df = 1, p-value = 0.08319
  • Conclusion : Le taux de vaccination est plus élevé dans les zones ruales (38.6%) que dans les zones urbaines (33.8%). Mais le text du chi-2 nous indique que la différence n’est pas tout à fait sigificative au seul habituel p < 0.05. Il faudrait prendre un risque d’erreur de 10% pour rejeter H0. Dans ce type de situation où la p-value est comprise entre 0.05 et 0.10 on ne dit pas qu’il n’y a pas de relation mais que l’échantillon d’enquête est de taille insuffisante pour conclure avec certitude à l’existence d’une relation.

4.4 Vaccination et instruction

# tableau de contingence
tabcont <- table(sel$ins4, sel$vac)
tabcont
       
        Non Oui
  Inf.  130  71
  Prim. 195 125
  Sec.  318 178
  Sup.  121  56
# Pourcentages
prop.table(tabcont,1)
       
              Non       Oui
  Inf.  0.6467662 0.3532338
  Prim. 0.6093750 0.3906250
  Sec.  0.6411290 0.3588710
  Sup.  0.6836158 0.3163842
# graphique
plot(tabcont)

# test
chisq.test(tabcont)

    Pearson's Chi-squared test

data:  tabcont
X-squared = 2.8062, df = 3, p-value = 0.4225
  • Conclusion : Le taux de vacination le plus élevé concerne les personnes ayant un niveau d’étude primaire (39%) et le plus faible les personnes ayant un niveau d’instruction supérieur (31.6%). Mais le test du chi-2 montre qu’il n’y a aucune relation entre le fait d’être vacciné et le niveau d’instruction (p= .42 > 0.05). C’est un résultat négatif mais intéressant car on aurait pu penser que le contraire serait vrai.